#ifndef CHEETAH_CORE_DEBUG_H
#define CHEETAH_CORE_DEBUG_H

#ifndef NDEBUG
#include "cheetah/core/settings.h"
#include "cheetah/core/error.h"

#include <time.h>
#include <stdio.h>
#endif

namespace cheetah {
namespace debug {
#ifndef NDEBUG
using namespace core;
#endif

inline void SetOutput(const char *filename) {
#ifndef NDEBUG
  freopen(filename, "a+", stderr);
#endif
}

template<typename T>
inline void Log(const char *info, const T *msg) {
#ifndef NDEBUG  
  fprintf(stderr, "%s: %s\n", info, msg);
  fflush(stderr);
#endif
}

template<typename T>
inline void Log(const char *info, const T *msg, bool sep) {
#ifndef NDEBUG
  fprintf(stderr, "--------------------------------------------------\n");
  Log(info, msg);
#endif
}

inline void Log(const char *info) { 
#ifndef NDEBUG
  fprintf(stderr, "%s\n", info);
  fflush(stderr);
#endif
}

inline void Log(const char *info, bool sep) {
#ifndef NDEBUG
  fprintf(stderr, "--------------------------------------------------\n");
  Log(info);
#endif
}

#ifndef NDEBUG
template<typename T>
struct LogTraits {
  static void Log(const char *info, const T val) {
    Warning("unsupported log type");
  }
};

#define MAPPING_LOG_TRAITS(T, STR)                  \
template<> struct LogTraits<T> {                    \
  static void Log(const char *info, const T val) {  \
    char buf[128];                                  \
    sprintf(buf, STR, val);                         \
    debug::Log(info, buf);                          \
  }                                                 \
};

MAPPING_LOG_TRAITS(int, "%d");
MAPPING_LOG_TRAITS(float, "%f");
MAPPING_LOG_TRAITS(unsigned int, "%u");
MAPPING_LOG_TRAITS(long, "%ld");

#endif

template<typename T>
inline void Log(const char *info, const T val) {
#ifndef NDEBUG
  LogTraits<T>::Log(info, val);
#endif
}

enum LogTimeType { kBegin, kEnd };
inline void LogTime(LogTimeType type, const char *info = "time") {
#ifndef NDEBUG
  static clock_t t1;
  if (type == kBegin) {
    t1 = clock();
  } else {
    clock_t t2 = clock();
    debug::Log(info, t2 - t1);
  }
#endif 
}

} // debug
} // cheetah
#endif // CHEETAH_CORE_DEBUG_H
